Skip to content

Add Github Copilot Provider#1254

Open
zortos293 wants to merge 5 commits intopingdotgg:mainfrom
zortos293:feat/copilot-integration
Open

Add Github Copilot Provider#1254
zortos293 wants to merge 5 commits intopingdotgg:mainfrom
zortos293:feat/copilot-integration

Conversation

@zortos293
Copy link
Contributor

@zortos293 zortos293 commented Mar 20, 2026

What Changed

  • Added Copilot provider support across the server, shared contracts, and web UI.
  • Wired up Copilot adapter/session/health handling and related model plumbing.
  • Fixed thread provider binding so threads stay attached to the correct provider.

Why

  • This makes Copilot available as a first-class provider while keeping provider selection and thread routing predictable.

UI Changes

  • Updated provider picker/settings surfaces to include Copilot-related behavior and provider health state.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Add GitHub Copilot as a supported provider across server, web, and contracts

  • Adds a full Copilot provider adapter in CopilotAdapter.ts that wires @github/copilot-sdk into the provider system, handling session lifecycle, turn tracking, event streaming, and model switching.
  • Registers the Copilot provider in the server layer, health checks, session directory, and adapter registry so it is available alongside Codex and Claude.
  • Adds Copilot models (GPT-5.4, Claude variants, Gemini 3.0 Pro), slug aliases, and default model to model.ts and updates contract schemas in orchestration.ts to accept 'copilot' as a valid provider kind.
  • Extends web app settings (appSettings.ts), the settings UI (_chat.settings.tsx), the composer (composerProviderRegistry.tsx), and the provider/model picker to expose Copilot configuration including CLI path, config directory, and custom models.
  • Adds a CLI path resolver (copilotCliPath.ts) that locates the bundled Copilot binary or npm loader across platforms and packaging layouts (Node/Electron).

Macroscope summarized 5c6b51e.


Note

Medium Risk
Introduces a new runtime provider backed by @github/copilot-sdk, including session/event mapping, model/effort validation, and a startup health probe that spawns/controls a Copilot client, which could impact stability across platforms.

Overview
Adds GitHub Copilot as a first-class provider end-to-end: new server CopilotAdapter layer (session lifecycle, turn streaming, tool/plan/usage event normalization, approvals + user-input requests, model switching with reasoning-effort validation) and wires it into ProviderAdapterRegistry, server layers, and persisted session provider decoding.

Introduces Copilot CLI discovery/override support (copilotCliPath, copilotConfigDir) with bundled binary resolution, plus a Copilot provider health check that starts the SDK client with a platform-aware timeout.

Updates the web app to expose Copilot in provider pickers/settings and to store/normalize Copilot-specific model options and custom models; also tweaks timeline rendering for tool/file-change entries (icon/title fallbacks and preferring changedFiles previews) and adds/adjusts tests accordingly.

Written by Cursor Bugbot for commit 5c6b51e. This will update automatically on new commits. Configure here.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 20, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35d60ebe-282f-4196-a89c-e0dfe692d545

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@zortos293 zortos293 marked this pull request as ready for review March 24, 2026 13:47
@zortos293 zortos293 force-pushed the feat/copilot-integration branch from 93bc16e to 1cc00a5 Compare March 25, 2026 09:39
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

@zortos293
Copy link
Contributor Author

This pr can now be reviewed im done with my stuff

});
}

const existing = sessions.get(input.threadId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low Layers/CopilotAdapter.ts:1679

Concurrent startSession calls for the same threadId race at the sessions.get check (line 1679): both callers find no existing session, both create new clients and sessions, and the second sessions.set (line 1778) overwrites the first. The first session's client and session become unreachable and leak. Consider synchronizing in-flight session creation, e.g., by tracking pending promises in a separate map keyed by threadId.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/CopilotAdapter.ts around line 1679:

Concurrent `startSession` calls for the same `threadId` race at the `sessions.get` check (line 1679): both callers find no existing session, both create new clients and sessions, and the second `sessions.set` (line 1778) overwrites the first. The first session's client and session become unreachable and leak. Consider synchronizing in-flight session creation, e.g., by tracking pending promises in a separate map keyed by `threadId`.

Evidence trail:
apps/server/src/provider/Layers/CopilotAdapter.ts line 844: `const sessions = new Map<ThreadId, ActiveCopilotSession>();` - plain Map with no synchronization
apps/server/src/provider/Layers/CopilotAdapter.ts line 1679: `const existing = sessions.get(input.threadId);` - the check
apps/server/src/provider/Layers/CopilotAdapter.ts lines 1720-1726: `yield* validateSessionConfiguration(...)` - first async yield point between check and set
apps/server/src/provider/Layers/CopilotAdapter.ts lines 1728-1763: `yield* Effect.tryPromise(...)` - second async yield point between check and set
apps/server/src/provider/Layers/CopilotAdapter.ts line 1778: `sessions.set(input.threadId, record);` - the set that overwrites any racing calls

...(input.cwd ? { cwd: input.cwd } : {}),
logLevel: "error",
};
const client = options?.clientFactory?.(clientOptions) ?? new CopilotClient(clientOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium Layers/CopilotAdapter.ts:1705

If session creation fails after client is instantiated (lines 1720–1778), the CopilotClientHandle is never cleaned up because client.stop() is only called in stopRecord, which requires the session to be in the sessions map. Since CopilotClient spawns a subprocess, this leaks orphan processes when validateSessionConfiguration fails or Effect.tryPromise throws. Consider wrapping client creation in Effect.acquireRelease to ensure client.stop() runs on failure.

-        const client = options?.clientFactory?.(clientOptions) ?? new CopilotClient(clientOptions);
+        const client = yield* Effect.acquireRelease(
+          Effect.sync(() => options?.clientFactory?.(clientOptions) ?? new CopilotClient(clientOptions)),
+          (client) => Effect.promise(() => client.stop())
+        );
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/CopilotAdapter.ts around line 1705:

If session creation fails after `client` is instantiated (lines 1720–1778), the `CopilotClientHandle` is never cleaned up because `client.stop()` is only called in `stopRecord`, which requires the session to be in the `sessions` map. Since `CopilotClient` spawns a subprocess, this leaks orphan processes when `validateSessionConfiguration` fails or `Effect.tryPromise` throws. Consider wrapping client creation in `Effect.acquireRelease` to ensure `client.stop()` runs on failure.

Evidence trail:
apps/server/src/provider/Layers/CopilotAdapter.ts lines 1700-1705 (client instantiation), lines 1720-1725 (validateSessionConfiguration call), lines 1460-1527 (validateSessionConfiguration definition with client.start() at line 1471 and multiple failure points), lines 1727-1759 (session creation that can fail), lines 1764-1772 (record added to sessions only after all succeeds), lines 1639-1661 (stopRecord function definition), line 1647 (only location where client.stop() is called). No Effect.acquireRelease/ensuring/onInterrupt patterns found via git_grep.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant